package com.atguigu.gmall.order.service.impl;

import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.mqconstant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.config.OrderInfoConfig;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.client.feign.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;

/**
 * @author wk
 * @create 2021-09-10 23:23
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Value("${ware.url}")
    private String wareUrl;

    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CartInfoMapper cartInfoMapper;
    @Autowired
    private RabbitService rabbitService;

    // 库存服务返回结果 如果又则返回1 否则返回0
    @Override
    public boolean hasStock(OrderDetail orderDetail) {
        // http://www.gware.com/hasStock?skuId=10221&num=2
        // 如果和1相等则表示有库存 否则返回0
        return "1".equals(HttpClientUtil.doGet(wareUrl + "/hasStock?skuId="
                + orderDetail.getSkuId() + "&num=" + orderDetail.getSkuNum()));
    }

    // 保存订单 同时并将购物车中选中的商品删除
    @Override
    public Long saveOrder(OrderInfo orderInfo) {
        // 1.根据数据库表 填写订单信息
        // 1.1总金额
        orderInfo.sumTotalAmount();
        // 1.2订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        // 1.3订单交易编号 第三方
        // Calendar.getInstance().getTimeInMillis();
        String tradeNo = "WK" + System.currentTimeMillis() + " " + new Random().nextInt(1000);
        // RandomUtils.nextInt(0, 1000);
        orderInfo.setOutTradeNo(tradeNo);
        // 1.4订单描述
        StringBuilder builder = new StringBuilder();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        // 遍历订单描述 以商品名
        for (OrderDetail orderDetail : orderDetailList) {
            builder.append(orderDetail.getSkuName() + " ");
            // 同时对实时价格进行更新
            BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(skuPrice);
        }
        // 描述以100以内
        if (builder.toString().length() > 100) {
            String substring = builder.toString().substring(0, 100);
            orderInfo.setTradeBody(substring);
        } else {
            orderInfo.setTradeBody(builder.toString());
        }
        // 1.5创建时间
        Calendar calendar = Calendar.getInstance();
        orderInfo.setCreateTime(calendar.getTime());
        // 设置过期时间为2个小时
        calendar.add(Calendar.HOUR, 2);
        // 1.6失效时间
        orderInfo.setExpireTime(calendar.getTime());
        // 1.7进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        // 1.8设置总金额
        orderInfo.sumTotalAmount();
        // 2.保存订单
        orderInfoMapper.insert(orderInfo);
        // 2.1保存订单详情
        List<String> skuIdList = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {
            // 设置外键
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
            // 同时将商品集合id获取到
            skuIdList.add(orderDetail.getSkuId().toString());
        }
        // 需要将购物车中下单选中的商品删除
        // 3.更新DB 根据用户id和商品id
        cartInfoMapper.delete(new QueryWrapper<CartInfo>()
                .eq("user_id", orderInfo.getUserId())
                .in("sku_id", skuIdList)
        );
        // 4.更新缓存 删除已下单的商品
        String cacheKey =
                RedisConst.USER_KEY_PREFIX + orderInfo.getUserId() +
                        RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheKey, skuIdList.toArray());

        // 5.使用mq延迟消息 2小时后未支付则自动取消订单
        // 使用基于插件实现的延迟
        rabbitService.sendDelayedMessage(
                MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL, orderInfo.getId(), 150000);
        return orderInfo.getId();
    }

    @Override
    public void cancelOrder(Long orderId) {
        // 取消订单 先进行查询 该款商品的支付状态 如果是未支付 则进行支付状态更新 以及进程状态更新
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        // 如果订单状态不为空 且支付状态为未支付
        if (orderInfo != null && OrderStatus.UNPAID.name().equals(orderInfo.getOrderStatus())) {
            orderInfo.setId(orderId);
            // 1.更新支付状态
            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            // 2.更新进程状态
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
            // 更新数据库
            orderInfoMapper.updateById(orderInfo);
        }
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        return orderInfoMapper.selectById(orderId);
    }
}
